﻿using System;
using System.Collections.Generic;
using System.Linq;
using Castle.MonoRail.Framework;
using Castle.MonoRail.Framework.Filters;
using Castle.MonoRail.Framework.Helpers;
using StateTheater.Models;
using StateTheaterDataModel;
using Castle.Core;
using System.Text;
using System.Data.Linq;
using System.Globalization;
using StateTheater.Helpers;

namespace StateTheater.Controllers
{
	[Layout("default"), Rescue("generalerror")]
	[Filter(ExecuteWhen.BeforeAction, typeof(MobileFilter))]
	public class PlayController : SmartDispatcherController
	{
		StateTheaterDataContext db;

		private static readonly TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo;
		public static TextInfo TextInfo
		{
			get { return textInfo; }
//			set { textInfo = value; }
		}

		public PlayController(StateTheaterDataContext db)
		{
			this.db = db;
		}


		public void Display(int id)
		{
			PropertyBag["play"] = db.Plays.Where(pl => pl.PlayID == id).FirstOrDefault();
			PropertyBag["Authors"] = PlayController.GetAuthors(this.Context, id);

			PropertyBag["Productions"] = (from pr in db.Productions
												  where pr.PlayID == id
												  orderby pr.FirstPerformance descending
												  select new
												  {
													  Troupe= pr.Troupe.Name,
													  pr.ProductionID,
													  pr.FirstPerformance
												  }
													  ).ToList();

			GetProducts(id);
		}

		public void List()
		{
			List('A');
		}

		public void List(char letter)
		{
			var cat = from pl in db.Plays
					  where pl.SortTitle[0] == letter
					  orderby pl.SortTitle
					  select new NameId
					  {
						  Id = pl.PlayID,
						  Name = pl.Title
					  };
			var plays = cat.ToList();
			PropertyBag["list"] = plays;
			PropertyBag["letter"] = letter.ToString();

		}

		public void List(int ID)
		{
			Display(ID);

			Play play = PropertyBag["play"] as Play;
			List(play.SortTitle[0]);
		}

		public void GetProducts(int ID)
		{
			PropertyBag["Products"] = db.Products.Where(p => p.PlayID == ID).Select(p => new Pair<string, string>(p.Vendor,  p.Code));
		}
		// ------------------ WebServices--------------------------------------------------------------------------------------------
		public void FindPlaysText(string term, int limit)
		{
			CancelLayout();
			if (string.IsNullOrEmpty(term))
			{
				RenderText("");
			}
			else
			{
#if false
				(from p in db.Plays
				 where p.Title.Contains(term)
				 orderby p.SortTitle
				 select new
				 {
					 p.PlayID,
					 p.Title,
					 Comments = p.Comments ?? " ",
					 p.PlayCredits 
				 })
						.Take(limit)
						.ForEach(p => 
							{
								StringBuilder credits = new StringBuilder();
								p.PlayCredits.ForEach(pc => credits.AppendFormat("{0} by {1}, ", pc.CreditName.Credit, pc.People.FullName));
								RenderText(p.PlayID + "|" + p.Title + "|" + p.Comments.Replace('\n', ' ').Replace('\r', ' ') + "|" + credits.ToString() + Environment.NewLine);
							});
#else
				var pls = FindPlay(term, limit);
				foreach(var p in pls)
					RenderText(p.PlayID + "|" + p.Title + "|" + p.Comments.Replace('\n', ' ').Replace('\r', ' ') + "|" + p.Credits + Environment.NewLine);

#endif
			}

			this.HttpContext.Response.ContentType = "text/text";
			CancelView();

		}
		public void FindPlaysText(string term)
		{
			FindPlaysText(term, 10);
		}

		[Rescue(typeof(XmlRescueController))]
		[return: XmlReturnBinder]
		public PlayInfo[]  FindPlaysXml(string term)
		{
			return FindPlaysXml(term, 10);
		}
		[Rescue(typeof(XmlRescueController))]
		[return:XmlReturnBinder]
		public PlayInfo[] FindPlaysXml(string term, int limit)
		{
			return FindPlay(term, limit).ToArray();
		}

		[Rescue(typeof(JsonRescueController))]
		[return: JSONReturnBinder]
		public PlayInfo[] FindPlaysJson(string term)
		{
			return FindPlaysJson(term, 10);
		}
		[Rescue(typeof(JsonRescueController))]
		[return: JSONReturnBinder]
		public PlayInfo[] FindPlaysJson(string term, int limit)
		{
			return FindPlay(term, limit).ToArray();
		}



		private IEnumerable<PlayInfo> FindPlay(string term, int limit)
		{
			return (from p in db.Plays
			 where p.Title.Contains(term)
			 orderby p.SortTitle
			 select new
			 {
				 p.PlayID,
				 p.Title,
				 Comments = p.Comments ?? " ",
				 p.PlayCredits
			 })
					.Take(limit).ToList().Select(p =>
								new PlayInfo
									{
										Comments = p.Comments,
										Credits = p.PlayCredits.Aggregate(new StringBuilder(), (sb, pc) => sb.AppendFormat("{0} by {1}, ", pc.CreditName.Credit, pc.People.FullName)).ToString(),
										PlayCredits = null,
										PlayID = p.PlayID,
										Title = p.Title
									});

		}


		public class PlayInfo
		{
			public int PlayID { get; set; }
			public string Title { get; set; }
			public string Comments { get; set; }
			public EntitySet<PlayCredit> PlayCredits { get; set; }
			public string Credits { get; set; }
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public PlayInfo InfoJson(int PlayId)
		{
			var q = (from p in db.Plays
					 where p.PlayID == PlayId
					 select new PlayInfo
					 {
						 PlayID = p.PlayID,
						 Title = p.Title,
						 Comments = p.Comments ?? " ",
						 PlayCredits = p.PlayCredits,
					 }).FirstOrDefault();

			StringBuilder credits = new StringBuilder();
			q.PlayCredits.ForEach(pc => credits.AppendFormat("{0} by {1}, ", pc.CreditName.Credit, pc.People.FullName));
			q.Credits = credits.ToString();
			q.PlayCredits = null;

			return q;
		}

		[return:JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public int AddJson(string title, string comments)
		{
			CancelLayout();
			db.SubmitChanges();
			var play = new Play();

			title = TextInfo.ToTitleCase(title);

			play.Title = title;
			play.Comments = comments;
			play.SortTitle = Util.SEOEscape(title, true);
			db.Plays.InsertOnSubmit(play);
			db.SubmitChanges();

			PropertyBag["Play"] = play;
			AdminController.RecordUserAction(db, this, "AddPlay", play.PlayID, PropertyBag);

			return play.PlayID;
		}

		readonly Status OK = new Status("OK");
		readonly Status BAD = new Status("BAD");

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status UpdateComment(int id, string comments)
		{
			var play = db.Plays.FirstOrDefault(pl => pl.PlayID == id);
			if (play == null)
				return BAD;

			PropertyBag["oldComment"] = play.Comments;
			play.Comments = comments;
			db.SubmitChanges();

			PropertyBag["Play"] = play;
			AdminController.RecordUserAction(db, this, "UpdatePlayComment", play.PlayID, PropertyBag);

			return OK;
		}


// --------------------------------------------------------------------------------------------------------------

		public static List<Pair<string, string>> GetAuthors(IEngineContext engine, int id)
		{
			/*
			 * 	SELECT PlayCredit.CreditID, CreditNames.Credit + ' by ' AS Credit, RTRIM
					(People.FirstName) + ' ' + RTRIM (People.LastName) AS Name, PlayCredit.PersonID,
					case ISNULL(Photo,'') when  '' then 0 else 1 end as HasPhoto,
					case ISNULL(Bio,'') when  '' then 0 else 1 end as HasBio
				FROM (PlayCredit INNER JOIN CreditNames ON (PlayCredit.CreditID = 
					CreditNames.CreditID)) INNER JOIN People ON (PlayCredit.PersonID = People.PersonID)
				WHERE (PlayCredit.PlayID = @ID)
				ORDER BY PlayCredit.CreditID
			 */
			StateTheaterDataContext db = Util.DataContext;
		var siteRoot = engine.ApplicationPath;

			var Authors = from pc in db.PlayCredits
						  where pc.PlayID == id
						  orderby pc.CreditID
						  select new
						  {
							  Credit = pc.CreditName.Credit,

							  Name = new NameDetails
							  {
								  FirstName = pc.People.FirstName,
								  LastName = pc.People.LastName,
								  ID = pc.PersonID.Value,
								  HasPhoto = pc.People.Photo == null ? false : pc.People.Photo.Length > 0,
								  HasBio = pc.People.Bio == null ? false : pc.People.Bio.Length > 0
							  }
						  };

			List<Pair<string, string>> CreditLines = new List<Pair<string, string>>();
			string lastCredit = null;
			List<string> names = new List<string>();
			foreach (var cred in Authors)
			{
				if (cred.Credit != lastCredit)
				{
					if (names.Count > 0)
						CreditLines.Add(Pair.New(lastCredit, names.BuildList()));
					lastCredit = cred.Credit;
					names.Clear();

				}
				names.Add(FormatAuthorName(cred.Name, "AuthorName", siteRoot));
			}
			if (lastCredit != null)
				CreditLines.Add(Pair.New(lastCredit, names.BuildList()));

			return CreditLines;
		}

		private static string FormatAuthorName(NameDetails name, string className, string siteRoot)
		{
			return Span(className, LinkTo(name, siteRoot)) + (name.HasBio ? Span("HasBio", "") : "") + (name.HasPhoto?Span("HasPhoto","") : "");
			//			string fullName = name.FirstName.Trim() + " " + name.LastName.Trim();
			//			return Span(className, LinkTo(fullName, "person", "Display", name.ID, siteRoot));
		}

		private static string LinkTo(NameDetails name, string siteRoot)
		{
			return @"<a href=""{3}/Person/{0}/{1}/Display.rails"">{2}</a>".With(name.ID, 
				Util.SEOEscape(name.FullName, false), name.FullName, siteRoot);
		}
		private static string LinkTo(string innerContent, string controller, string action, int id, string siteRoot)
		{
			return @"<a href=""{4}/{0}/{1}.rails?id={2}"">{3}</a>".With(controller, action, id, innerContent, siteRoot);
		}

		private static string Span(string className, string innerText)
		{
			return "<span class=\"" + className + "\">" + innerText + "</span>";
		}

		/*
function FormatAuthorName(RS)
	dim str 
	str = "<a href=""person.asp?ID=" & RS("PersonID") & """>"
	str = str & "<font size=""5""><I>" & RS("NAME") & "</I></font>&nbsp;"
	if RS("HasBio") then 
		str = str & "<img SRC=""/images/hasbio.gif"" border=""0"" HSPACE=""0"" WIDTH=""16"" HEIGHT=""16"" \>"
	end if 
	if RS("HasPhoto") then 
		str = str & "<img SRC=""/images/hasphoto.gif"" border=""0"" HSPACE=""0"" WIDTH=""16"" HEIGHT=""16"" \>"
	end if
	str = str & "</a>"
	
	FormatAuthorName = str
end function
		*/


		/*
		 * <%
	LastCredit = ""
	CreditLine =""
	Names=""
	Do While CheckRS(RSPlay)
		Credit = RSPlay("Credit")
		if Credit <> LastCredit then
			Response.write replace(CreditLine, "NNNN", Names)
			LastCredit = Credit
			CreditLine = "<tr><td><font size=""4"">" & Credit & "</font>NNNN</td></tr>"
			Names = FormatAuthorName(RSPlay)
		else
			Names = Replace(Names," & ", ", ") & " & " + FormatAuthorName(RSPlay)
		end if
		RSPlay.MoveNext
	Loop
	Response.write replace(CreditLine, "NNNN", Names)
		 */
	}
}
